package com.lute.controller;

import java.util.ArrayList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.CommunicationException;
import org.springframework.security.oauth2.common.json.JSONException;
import org.springframework.security.oauth2.common.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.lute.json.ClientNameJSON;
import com.lute.model.ClientAdminProfile;
import com.lute.model.EmployeeAccountingPeriod;
import com.lute.model.EmployeeProfile;
import com.lute.model.User;
import com.lute.model.UserAccountState;
import com.lute.utils.LdapDAO;
import com.lute.utils.ServerErrorResponse;

@Controller
public class LoginServlet {
	
	@Autowired
	LdapDAO ldap;
		
	@RequestMapping(value = "/login", method = RequestMethod.POST,headers = "Content-type=application/json")
	public @ResponseBody String login(@RequestBody String credentialsJSON,HttpServletRequest request) throws JSONException {
		
		// TODO introduce time delays on multiple login/pass failures in the backend
		System.out.println(credentialsJSON);
		String result;
		String username;
		String password;
		JSONObject jsonReq;
		JSONObject jsonRes = new JSONObject();
		boolean ldapResult;
		
		try {
			jsonReq = new JSONObject(credentialsJSON);
			username = jsonReq.getString("login");
			password = jsonReq.getString("password");
		} catch(JSONException e) {
			jsonRes.put("result", ServerErrorResponse.MALFORMED_REQUEST.toString());
			result = jsonRes.toString();
			return result;
		}
		
		try {
			ldapResult = ldap.doAuthenticate(username, password);
		} catch(CommunicationException e) {
			jsonRes = new JSONObject();
			jsonRes.put("result", ServerErrorResponse.AUTHENTICATION_SERVICE_DOWN.toString());
			result = jsonRes.toString();
			return result;
		}
		try {
			
			if(ldapResult){
				User user = User.getUserFromDB("login",username);
				if(user == null) {
					user = (User)ldap.findUser(username);
					HttpSession session = request.getSession();
					session.setAttribute("firstName", user.getFirst_name());
					session.setAttribute("lastName", user.getLast_name());
					session.setAttribute("login", username);
					session.setAttribute("ldapEmail", user.getEmail());
					session.setAttribute("profile", "noProfile");
	
					jsonRes.put("userFirstName", user.getFirst_name());
					jsonRes.put("userLastName", user.getLast_name());
					jsonRes.put("userId", user.getId_user());
					jsonRes.put("userRole", "employee");
					jsonRes.put("employeeState", "noProfile");
					jsonRes.put("accountLocked", JSONObject.NULL);
					jsonRes.put("clientId", JSONObject.NULL);
					jsonRes.put("creativeHoursPercentage", JSONObject.NULL);
					jsonRes.put("employeeAccountingPeriodState", JSONObject.NULL);
					jsonRes.put("employeePosition", JSONObject.NULL);
					jsonRes.put("result", "OK");
				} else {
					/* save the user's session */
					HttpSession session = request.getSession();
					session.setAttribute("sessionUserId", user.getId_user());
					session.setAttribute("role", user.getRole().getName());
					session.setAttribute("profile", "exist");
					
					String role = user.getRole().getName();
					String isAccountLocked = user.getAccountLocked();
					String employeeState;
					String employeeAccPeriodState;
					Integer employeeClientId;
					jsonRes.put("employeeState", JSONObject.NULL);
					jsonRes.put("accountLocked", JSONObject.NULL);
					jsonRes.put("clientId", JSONObject.NULL);
					jsonRes.put("creativeHoursPercentage", JSONObject.NULL);
					jsonRes.put("employeeAccountingPeriodState", JSONObject.NULL);
					jsonRes.put("employeePosition", JSONObject.NULL);
					
					/* check employee current state and assigned client */
					if(role.equals("employee") || role.equals("approver")) {
						employeeState = EmployeeProfile.getEmployeeCurrentState(role, user.getId_user());
						employeeAccPeriodState = EmployeeAccountingPeriod.getCurrentEmployeeAccountinPeriodState(role, user.getId_user());
						employeeClientId = EmployeeProfile.getEmployeeClientId(role, user.getId_user());
						EmployeeProfile emplProfile = EmployeeProfile.getEmployeeProfileByEmployeeIdFromDB(role, user.getId_user());
						
						Integer positionPercentage = null;
						if(emplProfile.getPositions().getCreativity_percentage() != null) {
							positionPercentage = emplProfile.getPositions().getCreativity_percentage();
						}
						
						if(positionPercentage == null) {
							jsonRes.put("creativeHoursPercentage", JSONObject.NULL);
						} else {
							jsonRes.put("creativeHoursPercentage", Integer.toString(positionPercentage));
						}
						if(employeeState != null) jsonRes.put("employeeState", employeeState);
						if(employeeClientId != null) jsonRes.put("clientId", employeeClientId);
						if(employeeAccPeriodState != null)jsonRes.put("employeeAccountingPeriodState", employeeAccPeriodState);
						if(isAccountLocked.equals(UserAccountState.ACTIVE.toString())) {
							jsonRes.put("accountLocked", false);
						} else {
							jsonRes.put("accountLocked", true);
						}
						jsonRes.put("employeePosition", emplProfile.getPositions().getName());
					}
					/* check clientAdmin's clients assigned  */
					if(role.equals("clientAdmin")) {
						ClientAdminProfile clientAdminProfile = ClientAdminProfile.getClientAdminProfileByClientAdminIdFromDB(user.getId_user());
						if(clientAdminProfile.getDefaultClientId() != null) {
							jsonRes.put("clientId", clientAdminProfile.getDefaultClientId());
						}
						if(isAccountLocked.equals(UserAccountState.ACTIVE.toString())) {
							jsonRes.put("accountLocked", false);
						} else {
							jsonRes.put("accountLocked", true);
						}
					}
					/* prepare the json response */
					jsonRes.put("userFirstName", user.getFirst_name());
					jsonRes.put("userLastName", user.getLast_name());
					jsonRes.put("userId", user.getId_user());
					jsonRes.put("userRole", user.getRole().getName());
					jsonRes.put("result", "OK");
				}
				String commonName = user.getFirst_name()+" "+ user.getLast_name();
				ldap.modifyAttribute(commonName,"0");
				result = jsonRes.toString();
			}else {
				User user = (User)ldap.findUser(username);
				if(! (user == null) ) {
					String commonName = user.getFirst_name()+" "+ user.getLast_name();
					int currentLoginFailure = Integer.parseInt(ldap.getFailureNumber(commonName));
					System.out.println(currentLoginFailure);
					if(currentLoginFailure >= 5) {
						jsonRes.put("result", ServerErrorResponse.ACCOUNT_TEMPORARILY_LOCKED.toString());
					} else {
						jsonRes.put("result", ServerErrorResponse.BAD_CREDENTIALS.toString());
					}
					currentLoginFailure++;
					ldap.modifyAttribute(commonName,String.valueOf(currentLoginFailure));
				} else {
					jsonRes.put("result", ServerErrorResponse.BAD_CREDENTIALS.toString());
				}
				result = jsonRes.toString();
			}
		}catch(NullPointerException npe) {
			jsonRes.put("result", ServerErrorResponse.INTERNAL_ERROR.toString());
			result = jsonRes.toString();
			System.out.println(result);
			return result;
		}
		System.out.println(result);
		return result;
	}
}
